package cn.kmsoft.spatialboot.controller;

import cn.kmsoft.common.RestResponse;
import cn.kmsoft.common.exception.ExceptionMsg;
import cn.kmsoft.common.exception.ServiceException;
import cn.kmsoft.stgeometry.util.GeomUtil;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.spatialboot.common.object.StatQuery;
import cn.kmsoft.spatialboot.common.object.StatsFieldObject;
import cn.kmsoft.spatialboot.common.object.StatsParams;
import cn.kmsoft.spatialboot.service.SpatialAnalysisService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import static org.springframework.util.MimeTypeUtils.APPLICATION_JSON_VALUE;

/**
 * @author linglei
 * @date 2018/1/4.
 */
@RestController
@Api(description = "空间统计", tags = "3.Spatial Statistics")
@RequestMapping(produces = APPLICATION_JSON_VALUE)
public class SpatialStatController {

    private final SpatialAnalysisService spatialAnalysisService;

    @Autowired
    public SpatialStatController(SpatialAnalysisService spatialAnalysisService) {
        this.spatialAnalysisService = spatialAnalysisService;
    }

    @ApiOperation(value = "空间统计")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "instanceName", value = "实例名", paramType = "path", required = true),
            @ApiImplicitParam(name = "tableId", value = "表ID", paramType = "path", required = true),
            @ApiImplicitParam(name = "statQuery", value = "统计方式", paramType = "body", dataType = "StatQuery")
    })
    @RequestMapping(value = "/stat/{instanceName}/{tableId:.*}", method = RequestMethod.POST)
    public RestResponse analysis(@PathVariable String instanceName, @PathVariable String tableId,
                                 @RequestBody StatQuery statQuery) {
        return RestResponse.succeed(spatialAnalysisService.stat(instanceName, makeParams(tableId, statQuery)));
    }

    private StatsParams makeParams(String tableId, StatQuery statQuery) {
        StatsParams statsParams = new StatsParams();
        if (!StringUtil.isNullOrEmpty(statQuery.getGeometry())) {
            statsParams.setSpatialRel(statQuery.getSpatialRel());
            statsParams.setGeometryType(statQuery.getGeometryType());
            statsParams.setWkid(statQuery.getWkid());
            try {
                statsParams.setGeometry(GeomUtil.geomToWkt(statQuery.getGeometry().trim(), statsParams.getGeometryType()));
            } catch (Exception e) {
                throw new ServiceException(ExceptionMsg.CLIENT_ERROR, "the value of geometry is invalid");
            }
        }
        try {
            JSONArray statsFieldJsons = new JSONArray(statQuery.getStatsField());
            for (int i = 0; i < statsFieldJsons.length(); i++) {
                JSONObject statsFieldJson = statsFieldJsons.getJSONObject(i);
                StatsFieldObject statsObj = new StatsFieldObject();
                statsObj.setStatsType(statsFieldJson.getString("statisticType"));
                statsObj.setStatsField(statsFieldJson.getString("onStatisticField"));
                statsObj.setAliasName(statsFieldJson.getString("outStatisticFieldName"));
                statsParams.getStatsFields().add(statsObj);
            }

        } catch (JSONException e) {
            throw new ServiceException(ExceptionMsg.CLIENT_ERROR, "the value of statsField is invalid");
        }

        if (!StringUtil.isNullOrEmpty(statQuery.getGroupByField())) {
            try {
                JSONArray groupByFields = new JSONArray(statQuery.getGroupByField());
                for (int i = 0; i < groupByFields.length(); i++) {
                    statsParams.getGroupFields().add(groupByFields.getString(i));
                }

            } catch (JSONException e) {
                throw new ServiceException(ExceptionMsg.CLIENT_ERROR, "the value of groupByField is invalid");
            }
        }

        statsParams.setTableId(tableId);
        statsParams.setWhere(statQuery.getWhere());
        return statsParams;
    }
}
